1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#![allow(non_camel_case_types, non_snake_case)]

use crate::decl::*;
use crate::kernel::{ffi, privs::*};
use crate::prelude::*;

impl_handle! { HFILEMAPVIEW;
	/// Address of a
	/// [mapped view](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile).
	/// Originally just an `LPVOID`.
	///
	/// Unless you need something specific, consider using the
	/// [`FileMapped`](crate::FileMapped) high-level abstraction.
}

impl kernel_Hfilemapview for HFILEMAPVIEW {}

/// This trait is enabled with the `kernel` feature, and provides methods for
/// [`HFILEMAPVIEW`](crate::HFILEMAPVIEW).
///
/// Prefer importing this trait through the prelude:
///
/// ```no_run
/// use winsafe::prelude::*;
/// ```
pub trait kernel_Hfilemapview: Handle {
	/// Returns a slice representing the mapped memory. You can modify the
	/// contents. You should call this method only if the file has write access.
	///
	/// **Note**: If the file is resized to a smaller size, the slice will still
	/// map the bytes beyond the file. This may cause serious errors. So, if the
	/// file is resized, re-generate the slice by calling `as_slice` again.
	#[must_use]
	fn as_mut_slice(&self, len: usize) -> &mut [u8] {
		unsafe { std::slice::from_raw_parts_mut(self.ptr() as _, len) }
	}

	/// Returns a slice representing the mapped memory.
	///
	/// **Note**: If the file is resized to a smaller size, the slice will still
	/// map the bytes beyond the file. This may cause serious errors. So, if the
	/// file is resized, re-generate the slice by calling `as_slice` again.
	///
	/// # Examples
	///
	/// Reading the contents of a file into a string:
	///
	/// ```no_run
	/// use winsafe::{self as w, prelude::*, co};
	///
	/// let (hfile, _) = w::HFILE::CreateFile(
	///     "C:\\Temp\\test.txt",
	///     co::GENERIC::READ,
	///     Some(co::FILE_SHARE::READ),
	///     None,
	///     co::DISPOSITION::OPEN_EXISTING,
	///     co::FILE_ATTRIBUTE::NORMAL,
	///     None,
	///     None,
	///     None,
	/// )?;
	///
	/// let hmap = hfile.CreateFileMapping(
	///     None,
	///     co::PAGE::READONLY,
	///     None,
	///     None,
	/// )?;
	///
	/// let view = hmap.MapViewOfFile(co::FILE_MAP::READ, 0, None)?;
	///
	/// let slice = view.as_slice(hfile.GetFileSizeEx()? as _);
	/// let text = std::str::from_utf8(slice)?;
	///
	/// println!("{}", text);
	/// # w::AnyResult::Ok(())
	/// ```
	#[must_use]
	fn as_slice(&self, len: usize) -> &[u8] {
		unsafe { std::slice::from_raw_parts(self.ptr() as _, len) }
	}

	/// [`FlushViewOfFile`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-flushviewoffile)
	/// function.
	fn FlushViewOfFile(&self,
		start_at_byte: usize,
		num_bytes: usize,
	) -> SysResult<()>
	{
		bool_to_sysresult(
			unsafe {
				ffi::FlushViewOfFile(
					self.ptr().offset(start_at_byte as _),
					num_bytes,
				)
			},
		)
	}
}